#include "Parser.h"
#include "PKB.h"
#include "DesignExtractor.h"
#include <iostream>
#include "QueryProcessor.h"
#include "StmtTable.h"
using namespace std;

void toLowerCase(string &str);

void displayAST(TNode* node) {
	int l = (*node).getLevel();
	for (int i=0; i<l; i++) {
		cout<< " ";
	}
	cout << (*node).getLevel() << " " << (*node).getNodeType() << " " << (*node).getProcLine() << " " << (*node).getNumOfMoreChild() << endl;
	int n = (*node).getNumOfMoreChild();
	for (int i=0; i<n; i++) {
		TNode* p = *((*node).getMoreChildren()+i);
		displayAST(p);
	}
}

void displayVarTable(VarTable varTable) {
	cout << "========================VarTable==========================" << endl;
	int size = varTable.getSize();
	for (int i=0; i<size; i++) {
		cout << i << ". " << varTable.getVarName(i) << endl;
	}
}

void displayProcTable(ProcTable procTable) {
	cout << "========================ProcTable==========================" << endl;
	int size = procTable.getSize();
	for (int i=0; i<size; i++) {
		cout << i << ". " << procTable.getProName(i) << endl;
	}
}

void displayConstTable(ConstTable constTable) {
	cout << "========================ConstTable==========================" << endl;
	int size = constTable.getSize();
	for (int i=0; i<size; i++) {
		cout << i << ". " << constTable.getConstant(i) << endl;
	}
}

void displayFollows(Follows follows) {
	cout << "========================Follows==========================" << endl;
	int size = follows.getFollowsSize();
	for (int i=0; i<size; i++) {		
		cout << follows.getFollowsPair().at(i).first << "    " << follows.getFollowsPair().at(i).second << endl;
	}
}

void displayParent(Parent parent) {
	cout << "========================Parent==========================" << endl;
	int size = parent.getParentSize();
	for (int i=0; i<size; i++) {
		cout << parent.getParentPair().at(i).first << "    " << parent.getParentPair().at(i).second << endl;
	}
}

void displayModifies(Modifies modifies) {
	cout << "========================Modifies==========================" << endl;
	int size = modifies.getModifiesSize();
	for (int i=0; i<size; i++) {
		cout << modifies.getModifies().at(i).getSecond() << "    " << modifies.getModifies().at(i).getThird() << endl;
	}
}

void displayUses(Uses uses) {
	cout << "========================Uses==========================" << endl;
	int size = uses.getUsesSize();
	for (int i=0; i<size; i++) {
		cout << uses.getUses().at(i).getSecond() << "    " << uses.getUses().at(i).getThird() << endl;
	}
}

void displayCalls(Calls calls) {
	cout << "========================Calls==========================" << endl;
	int size = calls.getCallSize();
	for (int i=0; i<size; i++) {
		cout << calls.getCalls().at(i).getSecond() << "    " << calls.getCalls().at(i).getThird() << endl;
	}
}

void displayPatternTree(vector<Pattern_node> vp, int i, int level) {
	Pattern_node p = vp[i];
	for (int i=0; i<level; i++) {
		cout << " "; 
	}
	cout << level << ". " << p.getData() << endl;
	if (p.getLeft()!=-1) {
		displayPatternTree(vp, p.getLeft(), level+1);
	}
	if (p.getRight()!=-1) {
		displayPatternTree(vp, p.getRight(), level+1);
	}
}

void displayPatternTable(PatternTable patternTable) {
	cout << "========================PatternTable==========================" << endl;
	int size = patternTable.getPatternSize();
	for (int i=0; i<size; i++) {
		cout << patternTable.getPatternTable().at(i).getLineNum() << "  " << patternTable.getPatternTable().at(i).getType();
		cout << "  " << patternTable.getPatternTable().at(i).getVarName() << endl;
		vector<Pattern_node> vp = patternTable.getPatternTable().at(i).getNodeTree();
		if (patternTable.getPatternTable().at(i).getType()==0) displayPatternTree(vp, 0, 1);
	}
}


void main(){
	Parser p = Parser("test1.txt");
	PKB pkb = PKB(&p);
	DesignExtractor de = DesignExtractor(&pkb);
	/*
	TNode* node = ast.getRoot();
	cout << "========================AST==========================" << endl;
	if ((*node).getNodeType()=="") {
	cout << "Error!" << endl;
	} else {
	displayAST(node);
	}

	displayVarTable(varTable);
	displayProcTable(procTable);
	displayConstTable(constTable);
	displayFollows(follows);
	displayParent(parent);
	displayModifies(modifies);
	displayUses(uses);
	displayCalls(calls);
	displayPatternTable(patternTable);*/
	/*
	string query = "Assign a; Select a";
	QueryProcessor qp = QueryProcessor(query, &ast, &varTable, &follows, &parent, &modifies, &uses);
	qp.queryPreprocessor();
	list<string> result = qp.queryEvaluator();
	list<string>::iterator it = result.begin();
	for(int i=0;i<result.size();i++){
	cout << *it << " ";					
	advance(it,1);
	}
	cout << endl;*/
	
	string query = "Assign a; Select a such that Next*(a,5)";
	QueryProcessor pq = QueryProcessor(&pkb);
	list<string> result = pq.processingQuery(query);
	list<string>::iterator it = result.begin();
	cout << result.size() << endl;
	for(int i=0;i<result.size();i++){
		cout << *it << " ";					
		it ++;
	}
	cout << endl;
	system("pause");
}
